using CodeSnippet.Config;
using CodeSnippet.Formats;

namespace CodeSnippet.Helpers
{
    /// <summary>
    /// Helper class to initiate the formatting process.
    /// </summary>
    public static class FormatHelper
    {
        #region Operations
        /// <summary>
        /// Format the given source.
        /// </summary>
        /// <param name="lang">Identifier representing the source code formatter to use.</param>
        /// <param name="editorConfig">Configuration to use for the formatting.</param>
        /// <param name="styleConfig">Configuration to use for the styling.</param>
        /// <param name="source">The source code to be formatted.</param>
        /// <param name="trim">Flag indicating whether or not extra leading tab characters will be trimmed.</param>
        /// <returns>The formatted source code.</returns>
        public static string Format(SupportedFormatType lang, IEditorConfig editorConfig, IStyleConfig styleConfig, string source, bool trim)
        {
            // Remove unwanted characters.
            source = PreprocessSource(source, new string(' ', editorConfig.TabSpaces), trim);
            var format = SupportedFormat.GetItem(lang).NewFormatInstance();
            format.Editor = editorConfig;
            format.Style = styleConfig;
            return format.FormatCode(source);
        }
        /// <summary>
        /// Processes the given source code to remove/replace unwanted characters.
        /// </summary>
        /// <param name="source">The source code to be formatted.</param>
        /// <param name="tabReplacement">Value to use to replace the TAB character.</param>
        /// <param name="trim">Flag indicating whether or not extra leading tab characters will be trimmed.</param>
        /// <returns></returns>
        private static string PreprocessSource(string source, string tabReplacement, bool trim)
        {
            var processed = source.Replace("\t", tabReplacement);
            if (trim)
            {
                var lines = processed.Split('\n');
                if (lines.Length > 0)
                {
                    var numCharsToTrim = lines[0].Length - lines[0].TrimStart(new[] {'\t', ' '}).Length;
                    for (var i = 0; i < lines.Length; i++)
                    {
                        if (lines[i].Length >= numCharsToTrim)
                        {
                            lines[i] = lines[i].Remove(0, numCharsToTrim);
                        }
                    }
                }
                processed = string.Join("\n", lines);
            }
            return processed;
        }
        #endregion Operations
    }
}